/**
 * @author 0283000115
 * @date 2018年3月3日-下午2:32:37
 */
package com.zte.claa.inficombo.csa.app.controller;

import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.UUID;

import javax.servlet.http.HttpServletRequest;

import org.json.JSONArray;
import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import com.zte.claa.inficombo.csa.app.controller.ret.SHMXElevatorRsp;
import com.zte.claa.inficombo.csa.app.model.dev.ResourceShadow;
import com.zte.claa.inficombo.csa.app.model.redis.AlarmCode;
import com.zte.claa.inficombo.csa.app.model.redis.AlarmData;
import com.zte.claa.inficombo.csa.app.model.redis.DevMeteData;
import com.zte.claa.inficombo.csa.app.service.csa.impl.BaseCacheManager;
import com.zte.claa.inficombo.csa.app.service.resrpt.ResIndexDataRptService;
import com.zte.claa.inficombo.csa.app.service.rptparse.ParserContainer;
import com.zte.claa.inficombo.csa.app.util.JsonUtils;

import io.swagger.annotations.ApiOperation;

/**
 * @author 0283000115
 * 
 * 该controller仅用于接收上海麦信电梯上报的指标及告警数据.
 * 
 * 按逻辑资源类型处理.
 */

@RestController
@RequestMapping("/zteclaa/shmx/elevator") 
public class SHMXElevatorRptController extends BaseController {
	// 时间戳格式.
	public static final String DATETIME_FORMAT = "yyyy-MM-dd HH:mm:ss";
	private SimpleDateFormat dtFormater = new SimpleDateFormat(DATETIME_FORMAT);
	// 上海麦信电梯的设备类型
	public static final String SHMX_ELEVATOR_DEVTP = "claa_shmx_elevator";
	// 电梯上报数据的公共字段... 
	public static final String COLLECT_TIME = "device_report_time";
	public static final String PLATFORM_RPT_TIME = "platform_report_time";
	
	public static final String FIRM_CODE = "firm_code";
	public static final String DEVICE_CODE = "device_code";
	
	// 设备上线事件码.
	public static final String DEVICE_ONLINE_CODE = "T07D02";
	public static final String DEVICE_OFFLINE_CODE = "T07D01";
	
	// logger
	private Logger logger = LoggerFactory.getLogger(SHMXElevatorRptController.class);
	// 时间格式化...
	// private SimpleDateFormat dtFormater = new SimpleDateFormat(DATETIME_FORMAT);
	
	@Autowired
	private ResIndexDataRptService resDataRptService;
	
	@Autowired
	private BaseCacheManager cacheManager;
	
	@Autowired
	private ParserContainer parserContainer;
	
	/**
	 * 电梯数据上报.
	 * 样例：
	  {"data":[
	  		{
	  		"firm_code":"MX3390",
	  		"device_code":"MX3390",
			"signal_intensity":"",
			"device_report_time":"2020-03-01 10:24:20",
			"platform_report_time":"2020-03-01 10:24:20",
			"floor":"38",
			"flat_state":"1",
			"have_people":0,		
			"magnetic_state":0
			}
		  ]
		}
	 */
	@ApiOperation(value = "指标数据上报", notes = "麦信电梯指标上报")
	@RequestMapping(value={"/datareport"})
	@ResponseBody
	public SHMXElevatorRsp datareport(HttpServletRequest request) throws Exception{		
		SHMXElevatorRsp ret = new SHMXElevatorRsp();
		String jsonStr = "";
		try{
			jsonStr = this.getJsonParam(request);
			logger.info("datareport json str: "+jsonStr);
			JSONObject reqJson = new JSONObject(jsonStr);
			JSONArray jsonArr = reqJson.getJSONArray("data");
			int num = jsonArr.length();
			for(int i=0; i<num; i++){
				JSONObject json = jsonArr.getJSONObject(i);
				DevMeteData devMeteData = this.parseJson2Metedata(json);
				if(devMeteData != null){
					this.resDataRptService.submitResIndexData(devMeteData);	
				} 		
			}			
			ret.setCode(SHMXElevatorRsp.RET_SUCC);
			ret.setMessage("success");
		}catch(Exception e){
			logger.error("datareport process failed: "+jsonStr, e);
			ret.setCode(SHMXElevatorRsp.RET_ERR);
			ret.setMessage(e.getMessage());
		}
		return ret;		
	}
	
	// 构造deveui： formcode_deviceCode
	private String buildDevEui(String formCode, String deviceCode) {
		return formCode+"_"+deviceCode;
	}
	
	// 解析单个metedata对象. 
	private DevMeteData parseJson2Metedata(JSONObject json) throws Exception {
		HashMap<String, Object> data = new HashMap<String, Object>();
		Iterator<?> it = json.keys();
		// 遍历jsonObject数据，添加到Map对象
		while (it.hasNext()) {
			String key = String.valueOf(it.next());
			Object value = json.get(key);
			data.put(key, value);
		}
		DevMeteData devMeteData = new DevMeteData();
		String firmCode = data.remove(FIRM_CODE).toString();
		String deviceCode = data.remove(DEVICE_CODE).toString();
		firmCode = (firmCode == null) ? "" : firmCode.trim();
		deviceCode = (deviceCode == null) ? "" : deviceCode.trim();
		String devEui = this.buildDevEui(firmCode, deviceCode);
		if(devEui == null || devEui.equals("")){
			return null;
		}
		devMeteData.setDeveui(devEui);
		Object rptTsObj = data.remove(COLLECT_TIME);
		if(rptTsObj == null){
			rptTsObj = data.remove(PLATFORM_RPT_TIME);
		}
		if(rptTsObj != null && !rptTsObj.toString().equals("")){
			try{
				SimpleDateFormat dtFormater = new SimpleDateFormat(DATETIME_FORMAT);
				Date rptts = dtFormater.parse(rptTsObj.toString());
				devMeteData.setRpttime(new Timestamp(rptts.getTime()));
			}catch(Exception ignore){}
		}
		devMeteData.setMdata(data);
		return devMeteData;
	}
	
	/**
	 * 电梯告警上报.
	 * 
	 * @param request
	 * @return
	 * @throws Exception
	 */
	@ApiOperation(value = "电梯告警推送", notes = "上海麦信电梯告警推送")
	@RequestMapping(value={"/alarmreport"})
	@ResponseBody
	public SHMXElevatorRsp alarmrpt(HttpServletRequest request) throws Exception{		
		SHMXElevatorRsp ret = new SHMXElevatorRsp();
		String jsonStr = "";
		try{
			jsonStr = this.getJsonParam(request);
			logger.info("Receive alarm json str: "+jsonStr);
			JSONObject reqJson = new JSONObject(jsonStr);
			JSONArray jsonArr = reqJson.getJSONArray("data");
			int num = jsonArr.length();
			for(int i=0; i<num; i++){
				JSONObject paraJson = jsonArr.getJSONObject(i);
				String firmCode = JsonUtils.getJsonAttrVal(paraJson, FIRM_CODE, null);
				String deviceCode = JsonUtils.getJsonAttrVal(paraJson, DEVICE_CODE, null); 
				firmCode = (firmCode == null) ? "" : firmCode.trim();
				deviceCode = (deviceCode == null) ? "" : deviceCode.trim();
				String devId = this.buildDevEui(firmCode, deviceCode);
				
				if(devId == null || devId.equals("")){
					logger.warn("DevId parameter is invalid!");
					ret.setCode("1");
					ret.setMessage("缺少firmCode或deviceCode参数！");
					return ret;
				}
				ResourceShadow res = this.cacheManager.getRes(devId);
				if(res == null){
					logger.warn("Res not exist： "+devId);
					ret.setCode(SHMXElevatorRsp.RET_ERR);
					ret.setMessage("设备实例未配置!");
					return ret;
				}
				
				String deviceRptTime = JsonUtils.getJsonAttrVal(paraJson, COLLECT_TIME, "");
				String platformRptTime = JsonUtils.getJsonAttrVal(paraJson, PLATFORM_RPT_TIME, "");			
				String floor = JsonUtils.getJsonAttrVal(paraJson, "floor", "");
				String flatState = JsonUtils.getJsonAttrVal(paraJson, "flat_state", "-1");			
				String magneticState = JsonUtils.getJsonAttrVal(paraJson, "magnetic_state", "-1");
				String havePeople = JsonUtils.getJsonAttrVal(paraJson, "have_people", "-1");
				String orgDiscription = JsonUtils.getJsonAttrVal(paraJson, "warn_discription", "");
				String alarmCode = JsonUtils.getJsonAttrVal(paraJson, "warn_type", "");
				
				alarmCode = alarmCode.trim();			
				AlarmCode ac = this.cacheManager.getAlarmCode(res.getRestype(), alarmCode);
				String acodeDescp = (ac == null) ? "其他告警" : ac.getRemark();
				
				Date rptTime = null;
				if(!deviceRptTime.equals("")){
					rptTime = dtFormater.parse(deviceRptTime);
				} else if(!platformRptTime.equals("")){
					rptTime = dtFormater.parse(platformRptTime);
				} else {
					rptTime = new Date(System.currentTimeMillis());
				}
				
				String flatStateDescp = ("1".equalsIgnoreCase(flatState)) ? "平层" : "非平层";
				String magneticStateDescp = ("1".equalsIgnoreCase(magneticState)) ? "开门" : "关门";
				String havePeopleDescp = ("1".equalsIgnoreCase(havePeople)) ? "有人" : "无人";
				
				StringBuffer addInfoBuf = new StringBuffer();
				addInfoBuf.append("设备上报时间：").append(deviceRptTime).append("; ");
				addInfoBuf.append("平台上报时间：").append(platformRptTime).append("; ");
				addInfoBuf.append("楼层：").append(floor).append("; ");
				addInfoBuf.append("平层状态：(").append(flatState).append(")").append(flatStateDescp).append("; ");
				addInfoBuf.append("门磁状态：(").append(magneticState).append(")").append(magneticStateDescp).append("; ");
				addInfoBuf.append("是否有人：(").append(havePeople).append(")").append(havePeopleDescp).append("; ");
				addInfoBuf.append("报警信息：").append(orgDiscription).append("; ");
				
				// 构造Alarm
				AlarmData alarm = new AlarmData();
				alarm.setAlarmid("A"+Math.abs(UUID.randomUUID().getLeastSignificantBits()));
				alarm.setAlarmlevel(AlarmData.ALARM_LEVEL_1);
				alarm.setAlarmcode(alarmCode);
				if(DEVICE_ONLINE_CODE.equalsIgnoreCase(alarmCode)){
					alarm.setTypeflag(AlarmData.TPFLAG_CLEAR);
					alarm.setAlarmcode(DEVICE_OFFLINE_CODE);
				} else {
					alarm.setTypeflag(AlarmData.TPFLAG_ALARM);
				}
				alarm.setTitle(res.getResname()+"-"+acodeDescp);			
				alarm.setDeveui(devId);
				alarm.setDevtype(res.getRestype());
				alarm.setProjectid(res.getProjectid());
				alarm.setDevname(res.getResname());			
				alarm.setAlarmtime(new Timestamp(rptTime.getTime()));
				alarm.setDescp(addInfoBuf.toString());
				if(alarm.getTypeflag() == AlarmData.TPFLAG_CLEAR){
					alarm.setCleartime(new Timestamp(rptTime.getTime()));
				}
				alarm.setConfirmstate(AlarmData.CONFIRM_STATE_N);	
				alarm.setRemark(res.getRemark());
				// 发布告警.
				String alarmJson = JsonUtils.toJson(alarm);
				this.parserContainer.getAlarmPublisher().publishMessage(alarmJson);
				logger.info("[*^_^*]Publish alarm message ok: "+alarmJson);	
				ret.setCode(SHMXElevatorRsp.RET_SUCC);
				ret.setMessage("success");		
				// 如果是设备上线事件，补充发送一条上线通知消息.
				if(DEVICE_ONLINE_CODE.equalsIgnoreCase(alarmCode)){
					alarm.setTypeflag(AlarmData.TPFLAG_INFOM);
					alarm.setAlarmcode(alarmCode);
					alarm.setAlarmid("A"+Math.abs(UUID.randomUUID().getLeastSignificantBits()));
					alarmJson = JsonUtils.toJson(alarm);
					this.parserContainer.getAlarmPublisher().publishMessage(alarmJson);
					logger.info("[*^_^*]Publish fm information message ok: "+alarmJson);	
				}		
			}		
		}catch(Exception e){
			logger.error("alarmrpt msg process failed: "+jsonStr, e);
			ret.setCode(SHMXElevatorRsp.RET_ERR);
			ret.setMessage(e.getMessage());
		}
		return ret;
	}
}
